<?php
/**
 +------------------------------------------------------------------------------
 * 公共方法
 +------------------------------------------------------------------------------
 * @author  木頭
 * @version 1.2
 * @package ephp
 * @filename functions.php
 * @date 2009/12/17
 * @last modified 2010-12-13 15:21:31
 +------------------------------------------------------------------------------
 */

/** 类自动加载控制。 **/
function __autoload($classname)
{
	//dump($classname);
	#加载模型
	if(substr($classname,-5) == 'Model')
	{
		if(file_exists(APP_PATH.'/models/'.$classname.'.php'))
		{ require APP_PATH.'/models/'.$classname.'.php';}
		else
		{ throw new ephpException(APP_PATH.'/models/'.$classname.'.php 文件不存在!',1737);}

	}#加载控制器
	elseif(substr($classname,-10) == 'Controller')
	{
		if(file_exists(APP_PATH.'/controllers/'.$classname.'.php'))
		{ require APP_PATH.'/controllers/'.$classname.'.php';}
		else
		{
			if(! C('debug'))
			show_404();
			else
			throw new ephpException($classname.'没有定义，可能原因controllers/'.$classname.'.php不存在！',1738);
		}

	}
	else
	{#加载第三方库，位置在ext/下
		if( file_exists(APP_PATH.'/exts/'.$classname.'.class.php') )
		{ include APP_PATH.'/exts/'.$classname.'.class.php'; }
		elseif( file_exists(FW_PATH.'/exts/'.$classname.'.class.php') )
		{ include FW_PATH.'/exts/'.$classname.'.class.php'; }
		else
		{ throw new ephpException(APP_PATH.'/exts/'.$classname.'.class.php 文件不存在!',1739); }
	}
	return 0;
}

/** 设置error\exception异常处理函数。 **/
function error_handler($errno, $errstr, $errfile, $errline )
{
	#不显示系统错误，否则抛出exception异常
	if( ! C('show_errors') ) return true;

	# 抛出系统异常
	throw new ephpException($errstr, $errno, 0, $errfile, $errline);
}

/* 运行时间和占用内存,数据库查询次数 */
function run_info()
{
	global $run_start_time,$run_start_memory,$run_dbquery_count;

	echo '运行耗时：' . (microtime(1) - $run_start_time)*1000 . 'ms' . ' 使用内存：'
	. number_format((memory_get_usage() - $run_start_memory)/1024) .'K 数据库查询：'
	.$run_dbquery_count .'次';
}


/* dump输出后，停止 */
function dumpdie($thing)
{dump($thing);exit;}

/* print输出后，停止 */
function printdie($thing)
{dump($thing,null,0);exit;}

/**
 * 1.浏览器友好的变量输出，var支持任何变量，echo表示是否需要输出，如果为否，则返回要显示的字符串。
 * 2.Strict表示是否输出详细信息，如果为否，使用print_r输出，如果为是，使用var_dump输出。
 * 3.Dump函数还支持xdebug扩展
 * @param string  $var
 * @param boolean $echo
 * @param string  $label
 * @param boolean $strict
 * @return void
 */
function dump($var, $label=null, $strict=true, $echo=true )
{
    $label = empty($label) ? '' : '<h2 style="color: red;font: bold;">'. rtrim($label) . ":</h2>\n";
    if(!$strict)
    {
		$output = print_r($var, true);
		$output = "<pre>".$label.htmlspecialchars($output,ENT_QUOTES)."</pre>";
    }
    else
    {
        ob_start();
        var_dump($var);
        $output = ob_get_clean();
        if(!extension_loaded('xdebug'))
        {
            $output = preg_replace('/\]\=\>\n(\s+)/m', "] => ", $output);
            $output = '<pre>'. $label . htmlspecialchars($output, ENT_QUOTES). '</pre>';
        }
        else
        	$output = $label.$output;
    }

    if ($echo)
    {
        echo $output;
        return ;
    }
    else
        return $output;
}


/**
 * 读取config配置文件的value
 * @param string $name 获取配置名称, 缺省返回所有配置
 * @param string $config_name 从哪个配置文件中从获取，默认main
 * @param mixed  $value 要导入的value
 */
function C($name='', $config_name='main', $value=null)
{
    static $_config = array();

    #初始化$_config
    if(is_array($value))
    {
    	if(! array_key_exists($config_name,$_config)) $_config[$config_name] = array();
    	$_config[$config_name] = array_merge($_config[$config_name], $value);
    	return ;
    }
	else if(! is_null($value) )
	{//设置配置文件的值
		if($config_name === '') $config_name = 'main';
        if(! strpos($name,'.') )
        	$_config[$config_name][$name] = $value;
        else
        {
            $array = explode('.',$name);
			$_config[$config_name][$array[0]][$array[1]] = $value;
        }
        return ;
    }

    #加载其他配制文件
    if($config_name != 'main' && empty( $_config[$config_name] ))
    {
    	$filename = APP_PATH .'/conf/'. $config_name .'.config.php';
    	if( file_exists($filename) ) C('', $config_name, include $filename);
    	else throw new ephpException("错误：配置文件：$filename 不存在！",1404);
    }

    // 返回需要value
    if($name == '')
        return $_config[$config_name];
    else if( strpos($name,'.') )
    {
        $array = explode('.',$name );
        return isset($_config[$config_name][ $array[0] ][ $array[1] ]) ? $_config[$config_name][ $array[0] ][ $array[1] ] : false;
    }
    else if( array_key_exists($name, $_config[$config_name]) )
    {
        return $_config[$config_name][$name];
    }
    else
    {
        return false;
    }
}

/**
 * 快速创建model模型，相当于 new testModel()
 * @param string $model_name 模型名
 * @param string $db_config_name 要连接的数据库配制名，默认为空
 * @return object 模型对象
 */
function M($model_name, $db_config_name='')
{
	$model_name = $model_name . 'Model';
	$obj = new $model_name();

	if(! empty($db_config_name))
		$obj->dbconfig($db_config_name);
	return $obj;
}

/**
 * 不需要创建model文件，快速实例化模型对象
 * @param string $model_name 模型名
 * @param string $db_config 要连接的数据库配制，默认default
 * @return object
 */
function QM($model_name, $db_config_name='default')
{
	$obj = new model;
	$obj->dbconfig($db_config_name);
	$obj->table($model_name);
	return $obj;
}


/**
 +----------------------------------------------------------
 * write日志
 +----------------------------------------------------------
 * @param string $name log名称，如果带/则是文件夹
 * @param string $value log内容
 +----------------------------------------------------------
 * @return null
 +----------------------------------------------------------
 */
function wlog($name, $value)
{
	error_log($value."\n", 3, APP_PATH . '/runtime/logs/' . $name);
}



/**
 +----------------------------------------------------------
 * 数据缓存
 +----------------------------------------------------------
 * @param string $name 缓存名称
 * @param string $value 缓存值
 * @param integer $expire 缓存有效期
 +----------------------------------------------------------
 * @return array
 +----------------------------------------------------------
 */
function S($name,$value='',$expire=3600)
{
	include FW_PATH.'/exts/Filecache.class.php';
	return Filecache::cache($name,$value,$expire,'serialize');
}

/**
 * 文件缓存
 *
 * @param string $name 缓存名称
 * @param string $value 缓存的文件内存
 * @param integer $expire 有效期
 * @return string
 */
function F($name,$value='',$expire=3600)
{
	include FW_PATH.'/exts/Filecache.class.php';
	return Filecache::cache($name,$value,$expire,'array');
}


/**
 * URL装配车间,生成url，
 * 例子:U('index/help', array('id'=>25)) 或 U('index/help','id/15');
 * 那么可能生成：http://host/project/index.php/index/help/id/25.html
 *
 * @param string $base 控制器和方法
 * @param array  $param_arr url其他参数,接受参数array或string
 * @return string url 生成后的url字符串
 */
function U($base, $param_arr=array())
{
	#重载系统的U方法
	#if( function_exists('MY_U') ) return MY_U($base,$others_url);
	
	$urlx = '';
	if(C('url_type') != 'GET')
	{//生成PATH_INFO方式的url
		foreach ($param_arr as $k=>$v)
		{
			if($v !== '') $urlx.='/'.$k.'/'.$v;
		}
		return URL.'/'. $base . $urlx . C('html_url_suffix');
	}
	else
	{#GET方式的url
		$tarr = explode('/', $base);
		
		#第一个参数，出控制器和action外，可能包含其他的参数。
		foreach ($tarr as $k=>$v)
		{
			if($k == 0)		  $urlx .= '?controller='.$v;
			elseif($k == 1)   $urlx .= '&action='.$v;
			elseif($k%2 == 0) $urlx .= "&{$v}=";
			elseif($k%2 == 1) $urlx .= $v;
		}
			
		#第二个额外参数
		if(!empty($param_arr)) $urlx .= '&'.http_build_query($param_arr);
		
		return URL.$urlx;
	}
}


/**
 * 显示404页面，并发送404 header
 */
function show_404()
{
	#header('HTTP/1.1 404 Not Found');
	include FW_PATH.'/common/404.tpl.html';
	exit;
}

/**
 * 操作失败
 * @param string  $message 错误消息
 * @param string  $url 自动回跳的url
 * @param integer $wait 自动回跳等待时间，默认6s
 */
function show_error($message, $url='', $wait=6)
{
	#header('HTTP/1.1 500 Internal Server Error');
	if( $url == '' && !empty($_SERVER['HTTP_REFERER']) ) $url = $_SERVER['HTTP_REFERER'];

	include FW_PATH.'/common/500.tpl.html';
	exit;
}

/**
 * 操作成功
 * @param string  $message 提示信息
 * @param string  $url     自动回跳的url
 * @param integer $wait    自动回跳等待时间，默认6s
 */
function show_success($message, $url='', $wait=6)
{
	if( $url == '' && !empty($_SERVER['HTTP_REFERER']) ) $url = $_SERVER['HTTP_REFERER'];

	include FW_PATH.'/common/success.tpl.html';
	exit;
}

/**
 * 永久性质的跳转
 * @param string  $url 要跳转的url
 * @param integer $wait 跳转等待时间，默认0s
 * @param string  $message 提示信息
 */
function R($url,$wait=0,$message='')
{
	#header("HTTP/1.1 301 Moved Permanently");
    if(empty($message)) $message = "系统将在{$wait}秒之后自动跳转到{$url}！";
    if (!headers_sent() && (0===$wait) )
    {
        // redirect
        header("Content-Type:text/html; charset=UTF-8");
		header("Location: {$url}");
	}
    else
    {
    	//html refresh
    	#header("refresh:{$wait};url={$url}"); #直接发送header头。
		include FW_PATH.'/common/301.tpl.html';
		exit;
    }
}

/**
 * 获取$_GET中的值，如果不存在返回空字符串
 * 不传参数获取所有的get内容
 * @param string $variable_name
 * @param string $default_value
 */
function getv($variable_name = 0,$default_value='')
{
	if(! $variable_name) return $_GET;
	return empty($_GET[$variable_name])?$default_value:$_GET[$variable_name];
}

/**
 * 获取$_POST中的值，如果不存在返回空字符串
 * 不传参数获取所有的post内容
 * @param string $variable_name
 * @param string $default_value
 */
function postv($variable_name = 0,$default_value='')
{
	if(! $variable_name) return $_POST;
	return empty($_POST[$variable_name])?$default_value:$_POST[$variable_name];
}


//-----------------------------------------------------不常用函数
// xml编码
function xml_encode($data,$encoding='utf-8',$root="root")
{
	include FW_PATH.'/exts/Xml.class.php';
	$xml = new xml();
	return $xml->xml_encode($data,$encoding,$root);
}

#GBK To UTF-8
//function g2u($str)
//{
//	return iconv('gbk', 'utf-8',  $str);
//}
//#UTF-8 To GBK
//function u2g($str)
//{
//	return iconv('utf-8', 'gbk', $str);
//}

#模拟 C++ cin函数
//function cin()
//{
//	$fp = fopen('php://stdin', 'r');
//	$input = fgets($fp, 255);
//	fclose($fp);
//	$input = chop($input); // 去除尾部空白
//	return $input;
//}